﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Configuration;
using WMM.Tapioca.Instance;
using WMM.Tapioca;
using log4net.Core;
using log4net.Layout;
using log4net.Config;
using System.Diagnostics;
using WMM.Tapioca.Taxonomy;
using System.Xml.Schema;
using WMM.Tapioca.Linkbase;
using WMM.Tapioca.Validate;
using System.Net;
using System.Threading;
using System.Text.RegularExpressions;
using Tapioca.Utilities;
using System.Resources;
using mshtml;
using WMM.Tapioca.XbrlDimension;
using WMM.Tapioca.Formula;
using Tapioca.Model;
using WMM.Tapioca.Formula.Filters;
using log4net.Appender;
using System.Xml.Linq;
using System.Globalization;
using System.Xml;
using WMM.Tapioca.Utilities;

namespace Tapioca.Views
{
    public partial class MainForm : Form, IView
    {
        //static bool validateDTS = true;
        //static bool validateDimensionalTaxonomy = true;
        //static bool validateCalculation = false;
        //static bool validateFormula = false;

        string fileName;
        static string pathToDotFile;
        string diagramFile;        

        TreeView treeViewDts;
        TreeView tvPresentation;
        TreeView tvDefinition;
        TreeView tvCalculation;
        TreeView tvDimension;
        TreeView tvFormula;
        TreeView tvGeneric;

        XbrlDocument xbrlDoc;

        ProgressForm form1 = new ProgressForm();
        UserSettings userSettings = new UserSettings();
        public XmlTextEditorBase xmlTextEditor;

        public MainForm()
        {
            //Get the Default installed culture    
            Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.InstalledUICulture; 

            InitializeComponent();

            CreateRecentFileMenuItem();

            userSettings.LayoutEngine = "dot";
            userSettings.FileType = "png";
            userSettings.Save();            
        }


        # region Initialization

        private void CreateRecentFileMenuItem()
        {
            List<string> recentFilesOld = userSettings.RecentlyOpenedFiles;

            if (recentFilesOld == null)
            {
                recentFilesOld = new List<string>();
            }

            int k = 1;
            foreach (string recentFile in recentFilesOld)
            {
                ToolStripMenuItem recentFileToolStripMenuItem = new ToolStripMenuItem();
                recentFileToolStripMenuItem.Name = "recentFile" + k + "ToolStripMenuItem";
                recentFileToolStripMenuItem.Text = recentFile;
                recentFileToolStripMenuItem.Click += new System.EventHandler(this.recentFile1ToolStripMenuItem_Click);

                this.recentFilesToolStripMenuItem.DropDownItems.Add(recentFileToolStripMenuItem);
                k = k + 1;
            }
        }


        private void InitializeViews()
        {
            ResourceManager LocRM = new ResourceManager("Tapioca.Views.MainForm", System.Reflection.Assembly.GetExecutingAssembly());

        }


        private void InitializeSourceControl()
        {
            TabPage tabPageFile = new TabPage("File");

            this.xmlTextEditor = new XmlTextEditorBase();
            this.xmlTextEditor.Dock = System.Windows.Forms.DockStyle.Fill;
            this.xmlTextEditor.Location = new System.Drawing.Point(0, 0);
            this.xmlTextEditor.Name = "source";
            this.xmlTextEditor.ShowInvalidLines = false;
            this.xmlTextEditor.Size = new System.Drawing.Size(596, 323);
            this.xmlTextEditor.TabIndent = 2;
            this.xmlTextEditor.TabIndex = 0;
            
            tabPageFile.Controls.Add(this.xmlTextEditor);
            this.tabControlLinkbases.Controls.Add(tabPageFile);

            this.CreateContextMenu();
        }


        private void CreateContextMenu()
        {
            //contextmenu
            var mnu = new ContextMenuStrip();
            var mnuSave = new ToolStripMenuItem("Save Document");
            var mnuCopy = new ToolStripMenuItem("Copy to Clippboard");

            mnuSave.Click += new System.EventHandler(this.toolStripButtonSave_Click);
            mnuCopy.Click += new System.EventHandler(this.CopyToClipboard_Click);

            //Add to main context menu
            mnu.Items.AddRange(new ToolStripItem[] { mnuSave, mnuCopy });

            //Assign to datagridview
            this.xmlTextEditor.TextArea.ContextMenuStrip = mnu;
        }

        #endregion

        #region MVC pattern

        public void ModelChange(object sender, ModelChangeEventArgs e)
        {
            this.toolStripStatusLabel.Text = e.Message;

            Action action = () => this.toolStripStatusLabelMain.Refresh();
            this.toolStripStatusLabelMain.Invoke(action); 
            //Refresh();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            Controller.Instance.RegisterView(this);
        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Controller.Instance.UnregisterView(this);
        }       

        #endregion


        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            toolStripButtonOpen_Click(sender, e);
        }


        private void toolStripButtonOpen_Click(object sender, EventArgs e)
        {
            OpenFile();                    
        }


        XmlCachingResolver resolver;
        Stopwatch stopWatch;

        private void OpenFile()
        {
            ofd.FileName = String.Empty;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                ClearViews();

                this.tabControlMessages.SelectedIndex = 0;

                richTextBox1.Focus();

                fileName = ofd.FileName;

                UpdateListOfRecentFiles();

                resolver = new XmlCachingResolver(true);

                if (userSettings.Server.Length > 0)
                {
                    ICredentials myCred = new NetworkCredential(userSettings.UserName, userSettings.Password, userSettings.Domain);

                    try
                    {
                        resolver.ProxyServer = new WebProxy(userSettings.Server + ":" + userSettings.Port, true, new string[] { }, myCred);
                    }
                    catch (UriFormatException ex)
                    {
                        if (userSettings.Server.Length == 0)
                        {
                            MessageBox.Show("The proxy server must be configured");
                            return;
                        }

                        MessageBox.Show("Error on proxy: " + userSettings.Server + ":" + userSettings.Port + Environment.NewLine + ex.Message);
                        return;
                    }
                }

                stopWatch = Stopwatch.StartNew();

                toolStripButtonValidateDTS.Enabled = true;

                this.toolStripStatusLabel.Text = "DTS discovery...";
                this.toolStripStatusLabelMain.Refresh();

                backgroundWorkerOpenFile.RunWorkerAsync();

                //return true;
            }
            else
            {
                //return false;
            }
        }


        private void backgroundWorkerOpenFile_DoWork(object sender, DoWorkEventArgs e)
        {
            XbrlDocument xbrlDocument = null;

            try
            {
                xbrlDocument = new XbrlDocument(null, fileName, "", "", resolver);

                if (xbrlDocument.DocType == "xbrl")
                {
                    toolStripButtonCalculation.Owner.Invoke(new MethodInvoker(delegate { toolStripButtonCalculation.Enabled = true; }));
                    toolStripButtonFormula.Owner.Invoke(new MethodInvoker(delegate { toolStripButtonFormula.Enabled = true; }));

                    xbrlDoc = new InstanceDocument(xbrlDocument, resolver);

                    ValidateInstance vi = new ValidateInstance(xbrlDoc as InstanceDocument);
                }
                else if (xbrlDocument.DocType == "schema")
                {
                    toolStripStatusLabel.Owner.Invoke(new MethodInvoker(delegate { toolStripStatusLabel.Text = "Loading schema..." + xbrlDocument.FileName; }));

                    xbrlDoc = new TaxonomySchema(xbrlDocument, resolver);

                }
                else if (xbrlDocument.DocType == "linkbase")
                {
                    toolStripStatusLabel.Owner.Invoke(new MethodInvoker(delegate { toolStripStatusLabel.Text = "Loading linkbase..." + xbrlDocument.FileName; }));

                    xbrlDoc = new LinkbaseDocument(xbrlDocument, resolver);
                }
                else
                {
                    toolStripStatusLabel.Owner.Invoke(new MethodInvoker(delegate { toolStripStatusLabel.Text = "Loading xml document..." + xbrlDocument.FileName; }));

                    xbrlDoc = xbrlDocument;
                    xbrlDoc.Dts = new DTS(xbrlDocument, resolver);

                    ValidateXmlDoc();
                }

                toolStripStatusLabel.Owner.Invoke(new MethodInvoker(delegate { toolStripStatusLabel.Text = ""; }));
                Action action1 = () => this.toolStripStatusLabelMain.Refresh();
                this.toolStripStatusLabelMain.Invoke(action1);
            }
            catch (XmlException ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            catch (WebException ex)
            {
                MessageBox.Show("The proxy server must be configured\n" + ex.Message);
                return;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
        }


        private void backgroundWorkerOpenFile_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            InitializeSourceControl();

            this.xmlTextEditor.Text = File.ReadAllText(fileName);

            if (xbrlDoc == null)
            {
                return;
            }

            this.Text = "Tapioca - " + xbrlDoc.FileName;

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            richTextBox1.AppendText("Document loaded in " + ts.ToString(@"mm\:ss\.fff") + "\n");

            BuildViews();

        }        


        private void ValidateXmlDoc()
        {
            ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationHandler);

            try
            {
                XmlSchemaSet xmlSchemaSet = new XmlSchemaSet();

                foreach (TaxonomySchema taxonomySchema in xbrlDoc.Dts.TaxonomySchemas)
                {
                    if (taxonomySchema.ParentDocument is InstanceDocument)
                    {
                        xmlSchemaSet.Add(taxonomySchema.XmlSchemaSet);
                    }
                }

                richTextBox1.AppendText("Validating xml document: " + xbrlDoc.FileName + " targetNamespace:");
                xbrlDoc.ThisXDocument.Validate(xmlSchemaSet, eventHandler, true);
            }
            catch (XmlSchemaValidationException ex)
            {
                richTextBox1.AppendText("Validation error on ValidateInstance:" + ex.Message);
            }
        }


        private void ValidationHandler(object sender, ValidationEventArgs e)
        {
            richTextBox1.AppendText("Validation error on ValidateInstance, LineNumber:" + e.Exception.LineNumber + ":" + e.Exception.LinePosition);
        }


        private void UpdateListOfRecentFiles()
        {
            List<string> recentFilesOld = userSettings.RecentlyOpenedFiles;

            if (!recentFilesOld.Contains(fileName))
            {
                recentFilesOld.Add(fileName);
            }

            if (recentFilesOld.Count == 11)
            {
                recentFilesOld.RemoveAt(0);
            }

            userSettings.RecentlyOpenedFiles = recentFilesOld;
            userSettings.Save();
        }


        private void BuildViews()
        {
            Stopwatch stopWatch = Stopwatch.StartNew();

            CreateTreeViewDTS();

            CreateTreeViewLinkbases();

            ListAllConcepts();

            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            richTextBox1.AppendText("Build Views in " + ts.ToString(@"mm\:ss\.fff") + "\n");
        }


        private void CreateTreeViewDTS()
        {
            var tabDTS = new TabPage("DTS");
            treeViewDts = new TreeView();
            treeViewDts.Dock = System.Windows.Forms.DockStyle.Fill;
            treeViewDts.ContextMenuStrip = this.contextMenuStripDTS;
            this.treeViewDts.NodeMouseDoubleClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.treeViewDts_NodeMouseDoubleClick);

            tabDTS.Controls.Add(treeViewDts);
            this.tabControlDts.Controls.Add(tabDTS);

            TreeNode rootNode = new TreeNode(xbrlDoc.FileName);
            treeViewDts.Nodes.Add(rootNode);

            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if (xbrlDoc.DocType == "xbrl")
                {
                    if (currentSchema.ParentDocument != null && currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeNode schemaNode = new TreeNode() { Text = currentSchema.FileName, ForeColor = Color.FromName("Black"), Name = currentSchema.PathFile };
                        rootNode.Nodes.Add(schemaNode);

                        schemaNode = GetExternalSchema(currentSchema.XmlSchema, schemaNode);

                        foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                        {
                            if (currentLinkbase.Schema != null && currentLinkbase.Schema == currentSchema.XmlSchema)
                            {
                                TreeNode linkbaseNode = new TreeNode() { Text = currentLinkbase.FileName + " - linkbase", ForeColor = Color.FromName("Black"), Name = currentLinkbase.PathFile };
                                schemaNode.Nodes.Add(linkbaseNode);

                                linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                            }
                        }
                    }
                }
                else if (xbrlDoc.DocType == "schema")
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeNode schemaNode = new TreeNode() { Text = currentSchema.FileName, ForeColor = Color.FromName("Black"), Name = currentSchema.PathFile };
                        rootNode.Nodes.Add(schemaNode);
                    }

                    if (currentSchema.FileName == xbrlDoc.FileName)
                    {
                        rootNode = GetExternalSchema(currentSchema.XmlSchema, rootNode);

                        foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                        {
                            if (currentLinkbase.Schema != null && currentLinkbase.Schema == (xbrlDoc as TaxonomySchema).XmlSchema)
                            {
                                TreeNode linkbaseNode = new TreeNode() { Text = currentLinkbase.FileName + " - linkbase", ForeColor = Color.FromName("Black"), Name = currentLinkbase.PathFile };
                                rootNode.Nodes.Add(linkbaseNode);

                                linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                            }
                        }
                    }
                }
                else
                {
                    if (currentSchema.ParentDocument == xbrlDoc)
                    {
                        TreeNode schemaNode = new TreeNode() { Text = currentSchema.FileName, ForeColor = Color.FromName("Black"), Name = currentSchema.PathFile };
                        rootNode.Nodes.Add(schemaNode);
                    }

                    rootNode = GetExternalSchema(currentSchema.XmlSchema, rootNode);                    
                }
            }

            AddLinkbaseNode(rootNode);
        }


        private void AddLinkbaseNode(TreeNode instanceNode)
        {
            foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if (currentLinkbase.Instance != null && currentLinkbase.Instance == xbrlDoc)
                {
                    TreeNode linkbaseNode = new TreeNode() { Text = currentLinkbase.FileName + " - linkbase", ForeColor = Color.FromName("Black"), Name = currentLinkbase.PathFile };
                    instanceNode.Nodes.Add(linkbaseNode);

                    linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                }
            }
        }


        private TreeNode GetSchemaFromLinkbase(LinkbaseDocument linkbase, TreeNode linkbaseNode)
        {
            GetSchemaInXsiLocation(linkbase, linkbaseNode);

            //ArcRoleRef
            GetSchemaInArcRoleRef(linkbase, linkbaseNode);

            //RoleRef
            GetSchemaInRoleRef(linkbase, linkbaseNode);

            return linkbaseNode;
        }

        
        private void GetSchemaInArcRoleRef(LinkbaseDocument linkbase, TreeNode linkbaseNode)
        {
            IEnumerable<XElement> arcRolesRefNodes = from c in linkbase.ThisXDocument.Root.Elements()
                                                     where c.Name.LocalName.Equals("arcroleRef")
                                                     select c;

            foreach (XElement element in arcRolesRefNodes)
            {
                XNamespace ns = Constants.XLINK;
                string arcroleURI = (string)element.Attribute("arcroleURI") ?? string.Empty;
                XAttribute attrHref = element.Attribute(ns + "href");

                if (attrHref != null)
                {
                    HyperlinkReference xp = new HyperlinkReference(attrHref.Value);

                    if (!(xp.Url.Length == 0))
                    {
                        if (!ContainNodeName(linkbaseNode, xp))
                        {
                            TreeNode schemaNode = new TreeNode() { Text = GetFileName(xp.Url), ForeColor = Color.FromName("Black"), Name = xp.Url };
                            linkbaseNode.Nodes.Add(schemaNode);

                            schemaNode = GetExternalSchema(GetSchemaFromLinkbase(xp.Url), schemaNode);
                        }
                    }
                }
            }
        }


        private void GetSchemaInRoleRef(LinkbaseDocument linkbase, TreeNode linkbaseNode)
        {
            IEnumerable<XElement> rolesRefNodes = from c in linkbase.ThisXDocument.Root.Elements()
                                                     where c.Name.LocalName.Equals("roleRef")
                                                     select c;

            foreach (XElement element in rolesRefNodes)
            {
                XNamespace ns = Constants.XLINK;
                string arcroleURI = (string)element.Attribute("aroleURI") ?? string.Empty;
                XAttribute attrHref = element.Attribute(ns + "href");

                if (attrHref != null)
                {
                    HyperlinkReference xp = new HyperlinkReference(attrHref.Value);

                    if (!(xp.Url.Length == 0))
                    {
                        if (!ContainNodeName(linkbaseNode, xp))
                        {
                            TreeNode schemaNode = new TreeNode() { Text = GetFileName(xp.Url), ForeColor = Color.FromName("Black"), Name = xp.Url };
                            linkbaseNode.Nodes.Add(schemaNode);

                            schemaNode = GetExternalSchema(GetSchemaFromLinkbase(xp.Url), schemaNode);
                        }
                    }
                }
            }
        }


        private bool ContainNodeName(TreeNode linkbaseNode, HyperlinkReference xp)
        {
            foreach (TreeNode node in linkbaseNode.Nodes)
            {
                if (node.Name == xp.Url)
                {
                    return true;
                }
            }

            return false;
        }


        private void GetSchemaInXsiLocation(LinkbaseDocument linkbase, TreeNode linkbaseNode)
        {
            XNamespace xsi = Constants.XSI;
            string schemaLocation = (string)linkbase.ThisXDocument.Root.Attribute(xsi + "schemaLocation") ?? string.Empty;

            if (schemaLocation != null)
            {
                schemaLocation = schemaLocation.TrimEnd().TrimStart().Replace("  ", " ");
                schemaLocation = Regex.Replace(schemaLocation, @"\s+", " ");
                string[] schemaLocationSplit = schemaLocation.ToString().Split(' ');

                if (schemaLocationSplit.Length > 1)
                {
                    string Base = (string)linkbase.ThisXDocument.Root.Attribute("base") ?? string.Empty;
                    string baseUri = linkbase.ThisXDocument.Root.BaseUri;

                    for (int i = 0; i < schemaLocationSplit.Length; i = i + 2)
                    {
                        string fileName = schemaLocationSplit[i + 1];

                        TreeNode schemaNode = new TreeNode() { Text = GetFileName(fileName), ForeColor = Color.FromName("Black"), Name = fileName };
                        linkbaseNode.Nodes.Add(schemaNode);

                        schemaNode = GetExternalSchema(GetSchemaFromLinkbase(fileName), schemaNode);
                    }
                }
            }
        }


        private string GetFileName(string href)
        {
            string nameFile = href;
            int LastPathSeparator = href.LastIndexOf('/');

            if (LastPathSeparator == -1)
            {
                LastPathSeparator = href.LastIndexOf('\\');

                if (LastPathSeparator != -1)
                {
                    nameFile = href.Substring(LastPathSeparator + 1);
                }
            }

            nameFile = href.Substring(LastPathSeparator + 1);

            return nameFile;
        }


        private XmlSchema GetSchemaFromLinkbase(string fileName)
        {
            foreach (TaxonomySchema currentSchema in xbrlDoc.Dts.TaxonomySchemas)
            {
                if (currentSchema.FileName == GetFileName(fileName))
                {
                    return currentSchema.XmlSchema;
                }

                foreach (XmlSchemaObject schema in currentSchema.XmlSchema.Includes)
                {
                    XmlSchema externalSchema = null;

                    if (schema is XmlSchemaImport)
                    {
                        externalSchema = ((XmlSchemaImport)schema).Schema;

                        if (externalSchema.SourceUri == fileName)
                        {
                            return externalSchema;
                        }
                    }
                }
            }

            return null;
        }


        private TreeNode GetExternalSchema(XmlSchema currentSchema, TreeNode schemaNode)
        {
            if (currentSchema == null)
            {
                return schemaNode;
            }

            foreach (XmlSchemaObject schema in currentSchema.Includes)
            {
                XmlSchema externalSchema = null;

                if (schema is XmlSchemaImport)
                {
                    externalSchema = ((XmlSchemaImport)schema).Schema;

                    string schemaImportName = Path.GetFileName(externalSchema.SourceUri);

                    //TreeNode schemaImportNode = new TreeNode(schemaImportName);
                    TreeNode schemaImportNode = new TreeNode() { Text = schemaImportName, ForeColor = Color.FromName("Black"), Name = externalSchema.SourceUri };
                    schemaNode.Nodes.Add(schemaImportNode);

                    schemaImportNode = GetExternalSchema(externalSchema, schemaImportNode);

                    foreach (LinkbaseDocument currentLinkbase in xbrlDoc.Dts.LinkbaseDocuments)
                    {
                        if (currentLinkbase.Schema != null && currentLinkbase.Schema == externalSchema)
                        {
                            TreeNode linkbaseNode = new TreeNode() { Text = currentLinkbase.FileName + " - linkbase", ForeColor = Color.FromName("Black"), Name = currentLinkbase.PathFile };
                            schemaImportNode.Nodes.Add(linkbaseNode);

                            linkbaseNode = GetSchemaFromLinkbase(currentLinkbase, linkbaseNode);
                        }
                    }
                }
            }

            return schemaNode;
        }


        private void generateGraphToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            DTS dts = xbrlDoc.Dts;

            if (File.Exists("DTSGraph.dot"))
            {
                File.Delete("DTSGraph.dot");
            }

            pathToDotFile = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Tapioca\\DTSGraph.dot";

            DiagramGraphs.CreateDTSDotFile(xbrlDoc);

            GenDiagramFile();
        }      


        private static void AddNodesChild(StringBuilder content, TreeNode treeNode)
        {
            foreach (TreeNode treeNode2 in treeNode.Nodes)
            {
                //content.AppendLine("\t" + treeNode.Text.Replace(".", "") + " -> " + treeNode2.Text.Replace(".", "") + " [fontsize=8 fontcolor = grey fontname=Verdana,label=\"" + "schemaRef" + "\"];");
                content.AppendLine("\t\"" + treeNode.Text + "\" -> \"" + treeNode2.Text + "\" [fontsize=8 fontcolor = grey55 fontname=Verdana,label=\"" + "schemaRef" + "\"];");

                AddNodesChild(content, treeNode2);
            }            
        }


        private void CreateTreeViewLinkbases()
        {
            TabPage tabPagePresentation = null;
            TabPage tabPageDefinition = null;
            TabPage tabPageCalculation = null;

            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                // A presentation network
                if (ng.TupleNG.Item1.Equals("presentationLink"))
                {
                    if (tabPagePresentation == null)
                    {
                        tabPagePresentation = new TabPage("Presentation");
                        this.tvPresentation = new TreeView();
                        this.tvPresentation.Dock = System.Windows.Forms.DockStyle.Fill;
                        this.tvPresentation.Name = "tvPresentation";
                        this.tvPresentation.ContextMenuStrip = this.contextMenuStripLinkbases;

                        tabPagePresentation.Controls.Add(this.tvPresentation);
                        this.tabControlLinkbases.Controls.Add(tabPagePresentation);
                    }
                }
                else if (ng.TupleNG.Item1.Equals("definitionLink"))
                {
                    if (tabPageDefinition == null)
                    {
                        tabPageDefinition = new TabPage("Definition");
                        this.tvDefinition = new TreeView();
                        this.tvDefinition.Dock = System.Windows.Forms.DockStyle.Fill;
                        this.tvDefinition.Name = "tvDefinition";
                        this.tvDefinition.ContextMenuStrip = this.contextMenuStripLinkbases;

                        tabPageDefinition.Controls.Add(this.tvDefinition);
                        this.tabControlLinkbases.Controls.Add(tabPageDefinition);
                    }
                }
                else if (ng.TupleNG.Item1.Equals("calculationLink"))
                {
                    if (tabPageCalculation == null)
                    {
                        tabPageCalculation = new TabPage("Calculation");
                        this.tvCalculation = new TreeView();
                        this.tvCalculation.Dock = System.Windows.Forms.DockStyle.Fill;
                        this.tvCalculation.Name = "tvCalculation";
                        this.tvCalculation.ContextMenuStrip = this.contextMenuStripLinkbases;

                        tabPageCalculation.Controls.Add(this.tvCalculation);
                        this.tabControlLinkbases.Controls.Add(tabPageCalculation);
                    }
                }
                else
                {
                    if (!(ng.TupleNG.Item1.Equals("labelLink") && ng.TupleNG.Item1.Equals("referenceLink")) &&
                        !IsFormulaLinkbase())
                    {
                        TabPage tabPageGeneric = new TabPage(ng.TupleNG.Item1);
                        this.tvGeneric = new TreeView();
                        this.tvGeneric.Dock = System.Windows.Forms.DockStyle.Fill;
                        this.tvGeneric.Name = "tv" + ng.TupleNG.Item1.Replace("Link", "");
                        this.tvGeneric.ContextMenuStrip = this.contextMenuStripLinkbases;

                        tabPageGeneric.Controls.Add(this.tvGeneric);
                        this.tabControlLinkbases.Controls.Add(tabPageGeneric);
                    }
                }
            }

            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                // A presentation network
                if (ng.TupleNG.Item1.Equals("presentationLink"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeNode presentationNode = null;

                    if (!tvPresentation.Nodes.ContainsKey(definition))
                    {
                        presentationNode = new TreeNode(definition);
                        presentationNode.Name = definition;
                        tvPresentation.Nodes.Add(presentationNode);
                    }
                    else
                    {
                        presentationNode = tvPresentation.Nodes[definition];
                    }

                    TreeNode arcRoleNode = new TreeNode(ng.TupleNG.Item4);
                    presentationNode.Nodes.Add(arcRoleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeNode arcNode = new TreeNode(arc.FromId + " --> " + arc.ToId);
                        arcRoleNode.Nodes.Add(arcNode);
                    } 
                }

                // A definition network
                else if (ng.TupleNG.Item1.Equals("definitionLink")) 
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeNode definitionNode = null;

                    if (!tvDefinition.Nodes.ContainsKey(definition))
                    {
                        definitionNode = new TreeNode(definition);
                        definitionNode.Name = definition;
                        tvDefinition.Nodes.Add(definitionNode);
                    }
                    else
                    {
                        definitionNode = tvDefinition.Nodes[definition];
                    }

                    TreeNode arcRoleNode = new TreeNode(ng.TupleNG.Item4);
                    definitionNode.Nodes.Add(arcRoleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeNode arcNode = new TreeNode(arc.FromId + " --> " + arc.ToId);
                        arcRoleNode.Nodes.Add(arcNode);
                    }
                }

                else if (ng.TupleNG.Item1.Equals("calculationLink"))
                {
                    string definition = GetDefinitionOfRoleType(ng.TupleNG.Item2);

                    TreeNode definitionNode = null;

                    if (!tvCalculation.Nodes.ContainsKey(definition))
                    {
                        definitionNode = new TreeNode(definition);
                        definitionNode.Name = definition;
                        tvCalculation.Nodes.Add(definitionNode);
                    }
                    else
                    {
                        definitionNode = tvCalculation.Nodes[definition];
                    }

                    TreeNode arcRoleNode = new TreeNode(ng.TupleNG.Item4);
                    definitionNode.Nodes.Add(arcRoleNode);

                    foreach (Summation summation in ng.SummationConcepts)
                    {
                        TreeNode summationNode = new TreeNode(summation.SummationLocator.Label);
                        arcRoleNode.Nodes.Add(summationNode);

                        foreach (Locator locator in summation.ContributingLocators)
                        {
                            TreeNode contributingNode = new TreeNode(locator.Label);
                            summationNode.Nodes.Add(contributingNode);
                        }
                    }
                }
                else if (!ng.TupleNG.Item1.Equals("labelLink") && !ng.TupleNG.Item1.Equals("referenceLink") && !ng.TupleNG.Item1.Equals("link"))
                {
                    TreeNode roleNode = new TreeNode(ng.TupleNG.Item2);
                    tvGeneric.Nodes.Add(roleNode);

                    foreach (Arc arc in ng.NetworkRelationships)
                    {
                        TreeNode arcNode = new TreeNode(arc.FromId + " to " + arc.ToId);
                        roleNode.Nodes.Add(arcNode);
                    }
                }
            }


            if (IsFormulaLinkbase())
            {
                CreateTreeViewFormula();
            }

            if (IsDimensionalTaxonomy())
            {
                CreateTreeViewDimension();
            }
        }


        private string GetDefinitionOfRoleType(string roleUri)
        {
            foreach (RoleType roleType in xbrlDoc.Dts.RoleTypes)
            {
                if (roleType.RoleUri.Equals(roleUri))
                {
                    if (roleType.Definition != null)
                    {
                        return roleType.Definition;
                    }
                    else
                    {
                        return roleUri;
                    }
                }
            }

            return roleUri;
        }


        private void CreateTreeViewFormula()
        {
            TabPage tabPageFormula = new TabPage("Formula");
            this.tvFormula = new TreeView();
            this.tvFormula.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tvFormula.Name = "tvFormula";
            this.tvFormula.NodeMouseClick += new System.Windows.Forms.TreeNodeMouseClickEventHandler(this.tvFormula_MouseClick);
            this.tvFormula.ContextMenuStrip = this.contextMenuStripLinkbases;

            tabPageFormula.Controls.Add(this.tvFormula);
            this.tabControlLinkbases.Controls.Add(tabPageFormula);

            CreateAssertionsSet();

            // ValueAssertions

            CreateValueAssertions(this.tvFormula.Nodes, xbrlDoc.Dts.DtsFormula.ValueAssertions);

             // ExistenceAssertions

            CreateExistenceAssertions(this.tvFormula.Nodes, xbrlDoc.Dts.DtsFormula.ExistenceAssertions);

            // ConsistencyAssertions

            CreateConsistencyAssertions(this.tvFormula.Nodes, xbrlDoc.Dts.DtsFormula.ConsistencyAssertions);

            // Formulas

            CreateFormula();
        }


        private void CreateAssertionsSet()
        {
            foreach (AssertionSet assertionSet in xbrlDoc.Dts.DtsFormula.AssertionSets)
            {
                TreeNode idNode = new TreeNode("assertionSet " + assertionSet.Label);
                this.tvFormula.Nodes.Add(idNode);

                // ValueAssertions

                CreateValueAssertions(idNode.Nodes, assertionSet.ValueAssertions);

                // ExistenceAssertions

                CreateExistenceAssertions(idNode.Nodes, assertionSet.ExistenceAssertions);

                // ConsistencyAssertions

                CreateConsistencyAssertions(idNode.Nodes, assertionSet.ConsistencyAssertions);
            }
        }


        private void CreateValueAssertions(TreeNodeCollection nodes, List<ValueAssertion> valueAssertions)
        {
            foreach (ValueAssertion assertion in valueAssertions)
            {
                TreeNode idNode = new TreeNode("valueAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label));
                nodes.Add(idNode);

                foreach (FactVariable factVariable in assertion.FactVariables)
                {
                    TreeNode factVariableNode = new TreeNode("factVariable " + factVariable.Label);
                    idNode.Nodes.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeNode filterNode = new TreeNode("filter " + filter.ResourceName);
                        factVariableNode.Nodes.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeNode conceptNode = new TreeNode("concept " + conceptName);
                                filterNode.Nodes.Add(conceptNode);
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }
            }
        }


        private void CreateExistenceAssertions(TreeNodeCollection nodes, List<ExistenceAssertion> existenceAssertions)
        {
            foreach (ExistenceAssertion assertion in existenceAssertions)
            {
                TreeNode idNode = new TreeNode("existenceAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label));
                nodes.Add(idNode);

                foreach (FactVariable factVariable in assertion.FactVariables)
                {
                    TreeNode factVariableNode = new TreeNode("factVariable " + factVariable.Label);
                    idNode.Nodes.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeNode filterNode = new TreeNode("filter " + filter.ResourceName);
                        factVariableNode.Nodes.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeNode conceptNode = new TreeNode("concept " + conceptName);
                                filterNode.Nodes.Add(conceptNode);
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }
            }
        }


        private void CreateConsistencyAssertions(TreeNodeCollection nodes, List<ConsistencyAssertion> consistencyAssertions)
        {
            foreach (ConsistencyAssertion assertion in consistencyAssertions)
            {
                TreeNode idNode = new TreeNode("consistencyAssertion " + (assertion.Id != null ? assertion.Id : assertion.Label));
                nodes.Add(idNode);

                foreach (FormulaXBRL formula in assertion.FormulasXbrl)
                {
                    TreeNode formulaNode = new TreeNode("formula " + (formula.Id != null ? formula.Id : formula.Label));
                    idNode.Nodes.Add(formulaNode);

                    foreach (FactVariable factVariable in formula.FactVariables)
                    {
                        TreeNode factVariableNode = new TreeNode("factVariable " + factVariable.Label);
                        formulaNode.Nodes.Add(factVariableNode);

                        foreach (Filter filter in factVariable.Filters)
                        {
                            TreeNode filterNode = new TreeNode("filter " + filter.ResourceName);
                            factVariableNode.Nodes.Add(filterNode);

                            if (filter.ResourceName.Equals("conceptName"))
                            {
                                foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                                {
                                    TreeNode conceptNode = new TreeNode("concept " + conceptName);
                                    filterNode.Nodes.Add(conceptNode);
                                }
                            }
                        }
                    }
                }

                if (assertion.MessageSatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message satisfied" + assertion.MessageSatisfied.Label + " " + assertion.MessageSatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }

                if (assertion.MessageUnsatisfied != null)
                {
                    TreeNode MessageNode = new TreeNode("message unsatisfied" + assertion.MessageUnsatisfied.Label + " " + assertion.MessageUnsatisfied.Content);
                    idNode.Nodes.Add(MessageNode);
                }
            }
        }


        private void CreateFormula()
        {
            foreach (FormulaXBRL formula in xbrlDoc.Dts.DtsFormula.Formulas)
            {
                TreeNode formulaNode = new TreeNode("formula " + (formula.Id != null ? formula.Id : formula.Label));
                this.tvFormula.Nodes.Add(formulaNode);

                foreach (FactVariable factVariable in formula.FactVariables)
                {
                    TreeNode factVariableNode = new TreeNode("factVariable " + factVariable.Label);
                    formulaNode.Nodes.Add(factVariableNode);

                    foreach (Filter filter in factVariable.Filters)
                    {
                        TreeNode filterNode = new TreeNode("filter " + filter.ResourceName);
                        factVariableNode.Nodes.Add(filterNode);

                        if (filter.ResourceName.Equals("conceptName"))
                        {
                            foreach (string conceptName in (filter as ConceptNameFilter).ConceptNameValues)
                            {
                                TreeNode conceptNode = new TreeNode("concept " + conceptName);
                                filterNode.Nodes.Add(conceptNode);
                            }
                        }
                    }
                }
            }
        }


        private void CreateTreeViewDimension()
        {
            TabPage tabPageDimension = new TabPage("Dimension(DRS)");
            this.tvDimension = new TreeView();
            this.tvDimension.Dock = System.Windows.Forms.DockStyle.Fill;
            this.tvDimension.Name = "tvDimension";
            this.tvDimension.ContextMenuStrip = this.contextMenuStripLinkbases;

            tabPageDimension.Controls.Add(this.tvDimension);
            this.tabControlLinkbases.Controls.Add(tabPageDimension);

            foreach (DimensionalRelationshipSet drs in xbrlDoc.Dts.DtsDimension.DimensionalRelationshipSets)
            {
                string definition = GetDefinitionOfRoleType(drs.DRSRole);

                TreeNode drsRoleNode = null;

                if (!tvDimension.Nodes.ContainsKey(definition))
                {
                    drsRoleNode = new TreeNode(definition);
                    drsRoleNode.Name = definition;
                    tvDimension.Nodes.Add(drsRoleNode);
                }
                else
                {
                    drsRoleNode = tvDimension.Nodes[definition];
                }

                //TreeNode arcRoleNode = new TreeNode(ng.TupleNG.Item4);
                //definitionNode.Nodes.Add(arcRoleNode);

                //TreeNode roleNode = new TreeNode(drs.DRSRole);
                //this.tvDimension.Nodes.Add(roleNode);

                foreach (ConsecutiveRelationshipsSet crs in drs.ConsecutiveRelationshipsSets)
                {
                    TreeNode primaryItemNode = new TreeNode(crs.HasHypercube.PrimaryItem.Name);
                    drsRoleNode.Nodes.Add(primaryItemNode);

                    TreeNode hypercubeNode = new TreeNode(crs.HasHypercube.Hypercube.Concept.Name + (crs.HasHypercube.TargetRole == null ? "" : " via TargetRole -> " + crs.HasHypercube.TargetRole.AbsoluteUri));
                    primaryItemNode.Nodes.Add(hypercubeNode);

                    foreach (HypercubeDimension hypercubeDimension in crs.HypercubeDimensions)
                    {
                        TreeNode dimensionNode = new TreeNode(hypercubeDimension.Dimension.Concept.Name + (hypercubeDimension.TargetRole == null ? "" : " via TargetRole -> " + hypercubeDimension.TargetRole.AbsoluteUri));
                        hypercubeNode.Nodes.Add(dimensionNode);

                        foreach (DimensionDomain dimensionDomain in crs.DimensionDomains)
                        {
                            if (dimensionDomain.Dimension == hypercubeDimension.Dimension)
                            {
                                TreeNode domainNode = new TreeNode(dimensionDomain.Domain.Concept.Name + (dimensionDomain.TargetRole == null ? "" : " via TargetRole -> " + dimensionDomain.TargetRole.AbsoluteUri));
                                dimensionNode.Nodes.Add(domainNode);

                                foreach (DomainMember domainMember in crs.DomainMembers)
                                {
                                    if (dimensionDomain.Domain.Concept.Name.Equals(domainMember.Domain.Name))
                                    {
                                        TreeNode memberNode = new TreeNode(domainMember.Member.Name);
                                        domainNode.Nodes.Add(memberNode);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }


        private bool IsFormulaLinkbase()
        {
            foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if ((linkbase.NamespaceManager.HasNamespace("generic") || linkbase.NamespaceManager.HasNamespace("gen")
                    || linkbase.NamespaceManager.HasNamespace("xbrl-gen")) &&
                    linkbase.NamespaceManager.HasNamespace("variable"))
                {
                    return true;
                }
            }

            return false;
        }


        private bool HasLinkbase(string linkbase)
        {
            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                if (ng.TupleNG.Item1.Contains(linkbase))
                {
                    return true;
                }
            }

            return false;
        }


        private bool IsDimensionalTaxonomy()
        {
            foreach (NetworkGraph ng in xbrlDoc.Dts.NetworkGraphs)
            {
                if (ng.TupleNG.Item1.Contains("definition"))
                {
                    string dimensionalArcRoles = "http://xbrl.org/int/dim/arcrole/all" +
                                                 "http://xbrl.org/int/dim/arcrole/notAll" +
                                                 "http://xbrl.org/int/dim/arcrole/hypercube-dimension" +
                                                 "http://xbrl.org/int/dim/arcrole/dimension-domain" +
                                                 "http://xbrl.org/int/dim/arcrole/domain-member" +
                                                 "http://xbrl.org/int/dim/arcrole/dimension-default";

                    if (dimensionalArcRoles.Contains(ng.TupleNG.Item4))
                    {
                        return true;
                    }
                }
            }

            return false;
        }


        private void ListAllConcepts()
        {
            List<Concept> concepts = xbrlDoc.Dts.GetAllConcepts();

            DataTable table = new DataTable();
            //add in tables
            table.Columns.Add("Name", typeof(string));
            table.Columns.Add("Id", typeof(string));
            table.Columns.Add("Abstract", typeof(string));
            table.Columns.Add("Substitution Group", typeof(string));
            table.Columns.Add("Type", typeof(string));
            table.Columns.Add("Period Type", typeof(string));
            table.Columns.Add("Balance", typeof(string));

            foreach (Concept concept in concepts)
            {
                //add in rows
                table.Rows.Add(concept.Name, concept.Id, concept.SchemaElement.IsAbstract, concept.SchemaElement.SubstitutionGroup.Name,
                               concept.TypeName.Name, concept.PeriodTypeString, concept.BalanceString);
            }

            dgvConcepts.AutoGenerateColumns = true;
            dgvConcepts.DataSource = table;
        }

        Stopwatch stopWatchDTS;

        private void toolStripButtonValidateDTS_Click(object sender, EventArgs e)
        {
            //richTextBox1.Clear();
            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();            

            //XbrlManager xbrlManager = new XbrlManager(xbrlDoc as InstanceDocument);
            //xbrlManager.IsValidateCalculation = validateCalculation;
            //xbrlManager.IsValidateDTS = validateDTS;
            //xbrlManager.IsValidateDimensionalTaxonomy = validateDimensionalTaxonomy;
            //xbrlManager.IsValidateFormula = validateFormula;
            //xbrlManager.Validate();
            stopWatchDTS = Stopwatch.StartNew();

            backgroundWorkerValidateDTS.RunWorkerAsync();
        }


        private void backgroundWorkerValidateDTS_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            ValidateDts vDts = new ValidateDts(xbrlDoc.Dts);
            ValidateLinkbases vlb = new ValidateLinkbases(xbrlDoc.Dts);
            ValidateDimensionalTaxonomy vd = new ValidateDimensionalTaxonomy(xbrlDoc.Dts);
            ValidateLinkbaseFormula vlf = new ValidateLinkbaseFormula(xbrlDoc.Dts);
        }


        private void backgroundWorkerValidateDTS_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.toolStripStatusLabel.Text = "";
            this.toolStripStatusLabelMain.Refresh();

            stopWatchDTS.Stop();
            TimeSpan ts = stopWatchDTS.Elapsed;

            richTextBox1.AppendText("\nProcessing time of validation:" + ts.ToString(@"mm\:ss\.fff") + "\n");
        }        


        private void toolStripMenuItemClear_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }


        private void toolStripMenuItemCopy_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(richTextBox1.Text);
        }


        private void CopyToClipboard_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(this.xmlTextEditor.Text);
        }


        private void toolStripMenuItemFile_Click(object sender, EventArgs e)
        {
            saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
            saveFileDialog1.DefaultExt = "txt";
            saveFileDialog1.Title = "Save a File";
            saveFileDialog1.ShowDialog();            
        }


        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            // Get file name.
            string name = saveFileDialog1.FileName;
            // Write to the file name selected.
            File.WriteAllText(name, richTextBox1.Text);
        }


        private void proxyServerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ProxySetting window = new ProxySetting();

            window.Domain = userSettings.Domain;
            window.Server = userSettings.Server;
            window.Port = userSettings.Port;
            window.Username = userSettings.UserName;
            window.Password = userSettings.Password;

            if (window.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            userSettings.Domain = window.Domain;
            userSettings.Server = window.Server;
            userSettings.Port = window.Port;
            userSettings.UserName = window.Username;
            userSettings.Password = window.Password;
            userSettings.Save(); 

            //Tapioca.Properties.Settings.Default.user = "user";
            //Tapioca.Properties.Settings.Default.Save();

        }


        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ClearViews();
        }


        private void toolStripButtonClose_Click(object sender, EventArgs e)
        {
            toolStripButtonValidateDTS.Enabled = false;
            toolStripButtonCalculation.Enabled = false;
            toolStripButtonFormula.Enabled = false;

            ClearViews();
        }


        private void ClearViews()
        {
            richTextBox1.Clear();
            webBrowserMsg.Navigate("about:blank");
            webBrowserGraph.Navigate("about:blank");
            dgvConcepts.DataSource = null;

            if (this.xmlTextEditor != null)
            {
                RemoveXmlTextEditor(this.xmlTextEditor);
            }

            // Removes all the tab pages from tabControl.
            this.tabControlDts.TabPages.Clear();
            this.tabControlLinkbases.TabPages.Clear();

            Refresh();
        }


        private void RemoveXmlTextEditor(XmlTextEditorBase editor)
        {
            if (editor.Parent.Parent != null)
            {
                ((TabControl)editor.Parent.Parent).Controls.Remove(editor.Parent);
            }
        }


        /// <summary>Returns a list of all TreeView controls</summary>
        private IEnumerable<TabPage> AllTabsDts
        {
            get
            {
                return from t in tabControlDts.Controls.Cast<TabPage>()
                       select t;
            }
        }


        /// <summary>Returns a list of all TreeView controls</summary>
        private IEnumerable<TabPage> AllTabsLinkbase
        {
            get
            {
                return from t in tabControlLinkbases.Controls.Cast<TabPage>()
                       select t;
            }
        }


        /// <summary>Returns a list of all TreeView controls</summary>
        private IEnumerable<TreeView> AllTreeView
        {
            get
            {
                return from t in tabControlLinkbases.Controls.Cast<TabPage>()
                       from c in t.Controls.OfType<TreeView>()
                       select c;
            }
        }


        private void GenerateGraphDiagram(string linkbase, TreeNode selected)
        {
            new DiagramGraphs().CreateDotFile(selected.Text, linkbase, xbrlDoc, ref pathToDotFile);

            GenDiagramFile();                        
        }


        private void GenerateGraphDiagramFormula(TreeNode selected)
        {
            DiagramGraphs.CreateFormulaDotFile(selected.Text, xbrlDoc, ref pathToDotFile);

            GenDiagramFile();
        }


        private void tvFormula_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                tvFormula.SelectedNode = tvFormula.GetNodeAt(e.Location);
            }
        }               


        private void GenDiagramFile()
        {            
            form1.Show();

            backgroundWorker.RunWorkerAsync();
        }


        private void OnDoWork(object sender, DoWorkEventArgs e)
        {
            string fileType = userSettings.FileType;
            string engine = userSettings.LayoutEngine;

            diagramFile = pathToDotFile.Replace(".dot", "." + fileType);

            if (File.Exists(diagramFile))
            {
                File.Delete(diagramFile);
            }
            
            //MessageBox.Show(Environment.CurrentDirectory + @"\dot\dot" +" " + pathToDotFile + " -o " + diagramFile + " -T" + fileType + " -K" + engine + " -Goverlap=prism");

            ExecuteCommand(Environment.CurrentDirectory + @"\dot\dot", string.Format(@"""{0}"" -o ""{1}"" -T"
                           + fileType + " -K" + engine + " -Goverlap=prism", pathToDotFile, diagramFile));

            FileInfo f = new FileInfo(diagramFile);

            if (f.Length == 0)
            {
                ExecuteCommand(Environment.CurrentDirectory + @"\dot\dot", string.Format(@"""{0}"" -o ""{1}"" -Tpng -Ksfdp -Goverlap=prism",
                               pathToDotFile, diagramFile));
            }            
        }


        private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            form1.Hide();

            tabControlMessages.SelectedTab = tabPageGraphDiagram;
            webBrowserGraph.Focus();

            webBrowserGraph.Navigate(diagramFile + "?zoom=400%&navpanes=0&toolbar=0");
        }


        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (var dialog = new AboutBox())
            {
                dialog.ShowDialog(this);
            }
        }


        private static void ExecuteCommand(string command, string @params)
        {
            Process proc = new Process();
            proc.StartInfo = new ProcessStartInfo(command, @params) { CreateNoWindow = true, UseShellExecute = false };
            
            proc.Start();
            proc.WaitForExit();
        }


        private void generateGraphToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string linkbase = "";

            ToolStripItem menuItem = sender as ToolStripItem;

            if (menuItem != null)
            {
                ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;

                if (owner != null)
                {
                    // Get the control that is displaying this context menu
                    Control sourceControl = owner.SourceControl;
                    //sourceControl.sel
                    linkbase = FirstCharacterToLower(sourceControl.Name.Replace("tv", ""));
                }
            }

            if (linkbase == "formula")
            {
                GenerateGraphDiagramFormula(tvFormula.SelectedNode);
                return;
            }
            else if (linkbase == "definition")
            {
                GenerateGraphDiagram(linkbase, tvDefinition.SelectedNode);
                return;
            }
            else if (linkbase == "presentation")
            {
                GenerateGraphDiagram(linkbase, tvPresentation.SelectedNode);
                return;
            }
            else if (linkbase == "calculation")
            {
                GenerateGraphDiagram(linkbase, tvCalculation.SelectedNode);
                return;
            }
            else if (linkbase == "dimension")
            {
                GenerateGraphDiagram(linkbase, tvDimension.SelectedNode);
                return;
            }
            //GenerateGraphDiagram(linkbase);
            GenerateGraphDiagram(linkbase, tvDefinition.SelectedNode);
        }


        public static string FirstCharacterToLower(string str)
        {
            if (String.IsNullOrEmpty(str) || Char.IsLower(str, 0))
                return str;

            return Char.ToLowerInvariant(str[0]).ToString() + str.Substring(1);
        }


        private void viewLinkbaseFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string linkbaseName = "";
             
            ToolStripItem menuItem = sender as ToolStripItem;

            if (menuItem != null)
            {
                ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;

                if (owner != null)
                {
                    // Get the control that is displaying this context menu
                    Control sourceControl = owner.SourceControl;
                    linkbaseName = sourceControl.Name.Replace("tv", "").ToLower();
                }
            }

            if (linkbaseName == "formula")
            {
                foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
                {
                    if ((linkbase.NamespaceManager.HasNamespace("generic") || linkbase.NamespaceManager.HasNamespace("gen")
                        || linkbase.NamespaceManager.HasNamespace("xbrl-gen")) &&
                        linkbase.NamespaceManager.HasNamespace("variable"))
                    {
                        webBrowserMsg.Navigate(linkbase.PathFile);
                        break;
                    }
                }
            }

            foreach (LinkbaseDocument linkbase in xbrlDoc.Dts.LinkbaseDocuments)
            {
                if (linkbase.RoleLinkbaseRef.Contains(linkbaseName))
                {
                    webBrowserMsg.Navigate(linkbase.PathFile);
                    break;
                }
            }

            tabControlMessages.SelectedTab = tabPageWebBrowser;
            webBrowserMsg.Focus();
        }

        
        private void toolStripButtonSave_Click(object sender, EventArgs e)
        {
            File.WriteAllText(fileName, this.xmlTextEditor.Text);            
        }


        protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, Keys keyData)
        {
            switch (keyData)
            {
                case (Keys.Control | Keys.S):
                    toolStripButtonSave.PerformClick();
                    break;
                case (Keys.Control | Keys.F):
                    toolStripButtonFind.PerformClick();
                    break;
                case (Keys.Control | Keys.O):
                    toolStripButtonOpen.PerformClick();
                    break;
                case (Keys.Alt | Keys.C):
                    toolStripButtonClose.PerformClick();
                    break;
                case (Keys.Alt | Keys.F4):
                    this.Close();;
                    break;
                case (Keys.Alt | Keys.D):
                    toolStripButtonValidateDTS.PerformClick();
                    break;
                case (Keys.Alt | Keys.K):
                    toolStripButtonCalculation.PerformClick();
                    break;
                case (Keys.Alt | Keys.F):
                    toolStripButtonFormula.PerformClick();
                    break;
            }

            return base.ProcessCmdKey(ref msg, keyData);
        }


        private void toolStripButtonFind_Click(object sender, EventArgs e)
        {
            FindAndReplaceWindow dialogFind = new FindAndReplaceWindow();

            dialogFind.ShowDialog(this);
                     
        }   


        private void viewLinkbaseFileToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(AppendNode(treeViewDts.Nodes));
        }


        private string AppendNode(TreeNodeCollection nodes)
        {
            StringBuilder sb = new StringBuilder();

            foreach (TreeNode node in nodes)
            {
                sb.AppendLine(node.Text);

                sb.AppendLine("\t" + AppendNode(node.Nodes));
            }

            return sb.ToString();
        }


        private TreeNode m_OldSelectNode;     

        private void treeViewDts_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            // Point where the mouse is clicked.
            Point p = new Point(e.X, e.Y);

            // Get the node that the user has clicked.
            TreeNode node = treeViewDts.GetNodeAt(p);
            if (node != null)
            {

                // Select the node the user has clicked.
                // The node appears selected until the menu is displayed on the screen.
                m_OldSelectNode = treeViewDts.SelectedNode;
                treeViewDts.SelectedNode = node;

                string fileName = node.Text.Replace(" - linkbase", "");

                webBrowserMsg.Navigate(node.Name);

                tabControlMessages.SelectedTab = tabPageWebBrowser;
                webBrowserMsg.Focus();
                //webBrowser.Refresh();

                // Highlight the selected node.
                treeViewDts.SelectedNode = m_OldSelectNode;
                m_OldSelectNode = null;
            }
        }


        private void recentFile1ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem menuItem = sender as ToolStripMenuItem;

            if (menuItem != null)
            {
                ClearViews();

                this.tabControlMessages.SelectedIndex = 0;
                richTextBox1.Focus();

                OpenRecentFile(menuItem.Text);
            }
        }


        private void OpenRecentFile(string recentFileName)
        {
            resolver = new XmlCachingResolver(true);

            if (userSettings.Server.Length > 0)
            {
                string domain = "BCDF001";

                ICredentials myCred = new NetworkCredential(userSettings.UserName, userSettings.Password, domain);

                try
                {
                    resolver.ProxyServer = new WebProxy(userSettings.Server + ":" + userSettings.Port, true, new string[] { }, myCred);
                }
                catch (UriFormatException ex)
                {
                    if (userSettings.Server.Length == 0)
                    {
                        MessageBox.Show("The proxy server must be configured");
                    }

                    MessageBox.Show("Error on proxy: " + userSettings.Server + ":" + userSettings.Port + Environment.NewLine + ex.Message);
                }
            }

            stopWatch = Stopwatch.StartNew();

            richTextBox1.Focus();

            fileName = recentFileName;

            toolStripButtonValidateDTS.Enabled = true;
            this.toolStripStatusLabel.Text = "DTS discovery...";
            this.toolStripStatusLabelMain.Refresh();

            backgroundWorkerOpenFile.RunWorkerAsync();
        }


        private void expandAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            treeViewDts.ExpandAll();
        }


        private void expandAllToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            ToolStripItem menuItem = sender as ToolStripItem;

            if (menuItem != null)
            {
                ContextMenuStrip owner = menuItem.Owner as ContextMenuStrip;

                if (owner != null)
                {
                    // Get the control that is displaying this context menu
                    if (owner.SourceControl is TreeView)
                    {
                        TreeView sourceControl = (TreeView)owner.SourceControl;
                        sourceControl.ExpandAll();
                    }
                }
            }
        }


        private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            HtmlElement head = webBrowserMsg.Document.GetElementsByTagName("head")[0];
            HtmlElement scriptEl = webBrowserMsg.Document.CreateElement("script");
            IHTMLScriptElement script_element = (IHTMLScriptElement) scriptEl.DomElement;

            script_element.text = " function disableSelection(){document.body.onselectstart=function(){return false;}; " + "document.body.ondragstart=function(){return false}}";
            head.AppendChild(scriptEl);
            //webBrowser.Document.InvokeScript("disableSelection");

        }


        private void toolStripButtonFormula_Click(object sender, EventArgs e)
        {
            this.toolStripStatusLabel.Text = "Validating Formula...";
            this.toolStripStatusLabelMain.Refresh();

            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();
            richTextBox1.Refresh();

            backgroundWorkerFormula.RunWorkerAsync();

        }


        private void backgroundWorkerFormula_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            FormulaProcessor vf = new FormulaProcessor(xbrlDoc.Dts, true);
        }


        private void backgroundWorkerFormula_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.toolStripStatusLabel.Text = "";
            this.toolStripStatusLabelMain.Refresh();

            webBrowserMsg.Visible = true;
            webBrowserMsg.Document.Encoding = "iso-8859-9";
            webBrowserMsg.Url = new Uri(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/Tapioca/FormulaMessages.html");
            tabControlMessages.SelectedTab = tabPageWebBrowser;
            webBrowserMsg.Focus();
            //Refresh();
        }


        private void toolStripButtonCalculation_Click(object sender, EventArgs e)
        {
            this.tabControlMessages.SelectedIndex = 0;
            richTextBox1.Focus();
            richTextBox1.Refresh();

            backgroundWorkerCalculation.RunWorkerAsync();
        }


        private void backgroundWorkerCalculation_DoWork(object sender, DoWorkEventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

            ValidateCalculations vc = new ValidateCalculations(xbrlDoc.Dts, true);
        }


        private void backgroundWorkerCalculation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.toolStripStatusLabel.Text = "";
            this.toolStripStatusLabelMain.Refresh();

            webBrowserMsg.Visible = true;
            webBrowserMsg.Url = new Uri(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "/Tapioca/CalculationMessages.html");
            tabControlMessages.SelectedTab = tabPageWebBrowser;
            webBrowserMsg.Focus();
        }        
       

        private void configureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AppSetting window = new AppSetting();

            if (window.ShowDialog(this) != DialogResult.OK)
            {
                return;
            }

            userSettings.LayoutEngine = window.Engine;
            userSettings.FileType = window.FileType;           
            userSettings.Save(); 
        }

        
        
    }
}
